package com.inforich.app.api.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.inforich.app.api.dto.LoginDTO;
import com.inforich.app.api.service.IAppLoginService;
import com.inforich.app.component.TokenUtil;
import com.inforich.app.constant.AuthConstants;
import com.inforich.appManage.domain.AppUser;
import com.inforich.appManage.domain.Contact;
import com.inforich.appManage.service.IAppRoleService;
import com.inforich.appManage.service.IAppUserService;
import com.inforich.appManage.service.IContactService;
import com.inforich.carManage.domain.Driver;
import com.inforich.carManage.service.IDriverService;
import com.inforich.common.core.domain.AjaxResult;
import com.inforich.common.core.text.Convert;
import com.inforich.common.enums.RoleCodeEnum;
import com.inforich.common.utils.StringUtils;
import com.inforich.system.service.ISysConfigService;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @description: some desc
 * @author: HJM
 * @date: 2022/10/27
 */
@Service
public class AppLoginServiceImpl implements IAppLoginService {

  @Autowired
  private IAppUserService appUserService;
  @Autowired
  private TokenUtil tokenUtil;
  @Autowired
  private IAppRoleService appRoleService;
  @Autowired
  private IContactService contactService;
  @Autowired
  private IDriverService driverService;
  @Value("${wdjn.RSAPrivateKey}")
  private String RSAPrivateKey;
  @Autowired
  private ISysConfigService sysConfigService;

  @Override
  public AjaxResult login(LoginDTO loginDto) {
    Boolean rsaEnable = getWdjnRsaEnable();
    String znmh_userName = decrypt(rsaEnable, loginDto.getZnmh_userName());
    String znmh_mobile = decrypt(rsaEnable, loginDto.getZnmh_mobile());
    String znmh_idNumber = decrypt(rsaEnable, loginDto.getZnmh_idNumber());
    String roleCode = loginDto.getRoleCode();
    // 参数校验
    if (!Validator.isMobile(znmh_mobile)) {
      return AjaxResult.error("手机号码不正确");
    }
    if (!IdcardUtil.isValidCard(znmh_idNumber)) {
      return AjaxResult.error("身份证格式不正确");
    }
    if (StrUtil.isNotBlank(roleCode) && !RoleCodeEnum.ROLE_CODES.contains(roleCode)) {
      return AjaxResult.error("无效的身份类型");
    }
    AppUser appUser = appUserService.getByAccount(znmh_idNumber);

    if (appUser == null && StrUtil.isBlank(roleCode)) {
      return AjaxResult.error(100, "没有账户，请先注册");
    }
    String token = "";

    // 司机不能自由注册，需由公司负责人添加
    Driver driver = driverService.getOne(new LambdaQueryWrapper<Driver>()
        .eq(Driver::getIdnumber, znmh_idNumber));

    // 非第一次登录(账户已存在)
    if (appUser != null) {
      if (AuthConstants.USER_STATUS_DISABLE.equals(appUser.getStatus())) {
        return AjaxResult.error("当前用户已禁用");
      } else {
        if (RoleCodeEnum.DRIVER.getRoleCode().equals(roleCode)) {
          if (driver == null) {
            return AjaxResult.error("请联系公司负责人添加信息");
          }
          addDriverContact(appUser, driver);
        }
        appUserService.update(new LambdaUpdateWrapper<AppUser>()
            .set(AppUser::getLastLoginTime, new Date())
            .eq(AppUser::getId, appUser.getId()));
        String currentRoleCode = appUserService.getRoleCodeByUserId(appUser.getId());
        if (StrUtil.isNotBlank(currentRoleCode)) {
          roleCode = currentRoleCode;
        }
        token = tokenUtil.createToken(appUser.getId(), roleCode);
        return AjaxResult.success(createToken(token, roleCode));
      }
    }

    // 第一次登录
    if (RoleCodeEnum.DRIVER.getRoleCode().equals(roleCode)) {
      if (driver == null) {
        return AjaxResult.error("请联系公司负责人添加信息");
      }
    }

    if (StrUtil.isBlank(roleCode)) {
      return AjaxResult.error("请选择身份类型");
    }
    appUser = new AppUser();
    appUser.setUserAccount(znmh_idNumber);
    appUser.setUserIdnumber(znmh_idNumber);
    appUser.setUserPhone(znmh_mobile);
    appUser.setUserName(znmh_userName);
    appUser.setLastLoginTime(new Date());
    appUserService.save(appUser);

    if (RoleCodeEnum.DRIVER.getRoleCode().equals(roleCode)) {
      addDriverContact(appUser, driver);
    }

    token = tokenUtil.createToken(appUser.getId(), roleCode);
    return AjaxResult.success(createToken(token, roleCode));
  }

  // 添加司机信息
  private void addDriverContact(AppUser appUser, Driver driver) {
    int count = contactService.count(new LambdaQueryWrapper<Contact>()
        .eq(Contact::getAppUserId, appUser.getId()));
    if (count > 0) {
      return;
    }
    Contact contact = new Contact();
    contact.setAppUserId(appUser.getId());
    contact.setContactName(appUser.getUserName());
    contact.setContactPhone(appUser.getUserPhone());
    contact.setAppRoleId(appRoleService.getIdByRoleCode(RoleCodeEnum.DRIVER.getRoleCode()));
    contact.setTransportCompanyId(driver.getTransportCompanyId());
    contact.setDriverId(driver.getId());
    contactService.save(contact);
  }

  private JSONObject createToken(String token, String roleCode) {
    JSONObject json = new JSONObject();
    json.put("token", token);
    json.put("roleCode", roleCode);
    return json;
  }

  /**
   * 是否开启RSA加解密
   */
  private Boolean getWdjnRsaEnable() {
    String wdjnRsaEnable = sysConfigService.selectConfigByKey("sys.wdjn.rsa");
    if (StringUtils.isEmpty(wdjnRsaEnable)) {
      return false;
    }
    return Convert.toBool(wdjnRsaEnable);
  }

  /**
   * RSA解密
   */
  @Override
  public String decrypt(Boolean enable, String content) {
    if (enable) {
      RSA rsa = new RSA(RSAPrivateKey, null);
//      try {
//        content = URLDecoder.decode(content, "utf-8");
//      } catch (UnsupportedEncodingException e) {
//        e.printStackTrace();
//        return "";
//      }
      return rsa.decryptStr(content, KeyType.PrivateKey);
    } else {
      return content;
    }
  }

}
